package com.ruoyi.common.utils.can;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.*;

/**
 * CAN总线IO工具类，支持开关量（数字量）和模拟量的读写操作
 * 支持通道范围：
 * - 开关量：1-48通道
 * - 模拟量输出：1-12通道（输出/采集）
 * - 模拟量采样：1-18通道（采集）
 */
public class CanIoTool implements AutoCloseable {
    private static final Logger log = LoggerFactory.getLogger(CanIoTool.class);

    // 基础参数
    private static final String DEFAULT_IP = "192.168.0.7";
    private static final int DEFAULT_PORT = 20108;
    private static final int DEFAULT_MODULE_ADDR = 1;
    private static final int SOCKET_TIMEOUT = 5000; // 超时时间(ms)
    private static final int FRAME_TOTAL_LENGTH = 10; // 帧总长度(字节)
    private static final int DATA_LENGTH = 8; // 数据域长度(字节)

    // 功能码
    private static final byte FUNC_WRITE_DIGITAL = 0x01;  // 开关量写入
    private static final byte FUNC_READ_DIGITAL = 0x02;   // 开关量读取
    private static final byte FUNC_ANALOG_SAMPLING_READ = 0x03; // 模拟量采样读取（1-18通道）
    private static final byte FUNC_DIGITAL_COMMON = 0x04; // 数字量通用（协议定义）

    // 模拟量功能码映射（通道范围 -> 功能码）
    private static final Map<String, Byte> ANALOG_WRITE_FUNC_MAP = new HashMap<>();
    private static final Map<String, Byte> ANALOG_READ_FUNC_MAP = new HashMap<>();

    // 模拟量采样通道范围与帧索引映射（1-18通道对应5个响应帧）
    private static final Map<String, Integer> ANALOG_SAMPLING_FRAME_INDEX_MAP = new HashMap<>();
    static {
        // 模拟量输出功能码映射
        ANALOG_WRITE_FUNC_MAP.put("1-4", (byte) 0x01);
        ANALOG_WRITE_FUNC_MAP.put("5-8", (byte) 0x02);
        ANALOG_WRITE_FUNC_MAP.put("9-12", (byte) 0x03);
        ANALOG_READ_FUNC_MAP.put("1-4", (byte) 0x05);
        ANALOG_READ_FUNC_MAP.put("5-8", (byte) 0x06);

        // 模拟量采样通道范围对应的响应帧索引（0-4）
        ANALOG_SAMPLING_FRAME_INDEX_MAP.put("1-4", 0);
        ANALOG_SAMPLING_FRAME_INDEX_MAP.put("5-8", 1);
        ANALOG_SAMPLING_FRAME_INDEX_MAP.put("9-12", 2);
        ANALOG_SAMPLING_FRAME_INDEX_MAP.put("13-16", 3);
        ANALOG_SAMPLING_FRAME_INDEX_MAP.put("17-18", 4);
    }

    // 成员变量
    private final String ip;
    private final int port;
    private final int moduleAddr;
    private Socket socket;
    private InputStream inputStream;
    private OutputStream outputStream;


    /**
     * 构造器：使用默认IP、端口和模块地址初始化连接
     */
    public CanIoTool() {
        this(DEFAULT_IP, DEFAULT_PORT, DEFAULT_MODULE_ADDR);
    }

    /**
     * 构造器：指定IP、端口和模块地址初始化连接
     *
     * @param ip         设备IP地址
     * @param port       端口号
     * @param moduleAddr 模块地址（1-255）
     */
    public CanIoTool(String ip, int port, int moduleAddr) {
        this.ip = ip;
        this.port = port;
        this.moduleAddr = validateModuleAddr(moduleAddr);
        try {
            this.connect();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        log.info("连接成功 - IP: {}, 端口: {}, 模块地址: {}", ip, port, moduleAddr);
    }


    /**
     * 核心方法：发送帧并接收响应（单帧响应）
     *
     * @param funcCode 功能码（帧第1字节）
     * @param data     数据域（8字节）
     * @return 设备响应帧（10字节）
     * @throws IOException 通信异常或数据域无效时抛出
     */
    private synchronized byte[] sendFrame(byte funcCode, byte[] data) throws IOException {
        if (data == null || data.length != DATA_LENGTH) {
            throw new IllegalArgumentException("数据域必须为8字节");
        }

        // 构造10字节帧：功能码(1) + 模块地址(1) + 数据域(8)
        byte[] sendFrame = new byte[FRAME_TOTAL_LENGTH];
        sendFrame[0] = funcCode;
        sendFrame[1] = (byte) moduleAddr;
        System.arraycopy(data, 0, sendFrame, 2, DATA_LENGTH);

        log.debug("发送帧 - 功能码: 0x{}, 地址: 0x{}, 数据域: {}",
                bytesToHex(new byte[]{funcCode}),
                bytesToHex(new byte[]{(byte) moduleAddr}),
                bytesToHex(data));

        outputStream.write(sendFrame);
        outputStream.flush();
        return receiveFrame(funcCode);
    }

    /**
     * 核心方法：发送帧并接收多帧响应（用于模拟量采样读取）
     *
     * @param funcCode  功能码（帧第1字节）
     * @param data      数据域（8字节）
     * @param frameCount 预期响应帧数
     * @return 设备响应帧列表（每个帧10字节）
     * @throws IOException 通信异常或校验失败时抛出
     */
    private synchronized List<byte[]> sendFrameMultiResponse(byte funcCode, byte[] data, int frameCount) throws IOException {
        if (data == null || data.length != DATA_LENGTH) {
            throw new IllegalArgumentException("数据域必须为8字节");
        }
        if (frameCount <= 0) {
            throw new IllegalArgumentException("预期帧数必须为正数");
        }

        // 构造并发送请求帧
        byte[] sendFrame = new byte[FRAME_TOTAL_LENGTH];
        sendFrame[0] = funcCode;
        sendFrame[1] = (byte) moduleAddr;
        System.arraycopy(data, 0, sendFrame, 2, DATA_LENGTH);

        log.debug("发送多帧请求 - 功能码:0x{}, 地址:0x{}, 数据域:{}, 预期响应帧数:{}",
                bytesToHex(new byte[]{funcCode}),
                bytesToHex(new byte[]{(byte) moduleAddr}),
                bytesToHex(data),
                frameCount);

        outputStream.write(sendFrame);
        outputStream.flush();

        // 接收并校验所有响应帧
        List<byte[]> respFrames = new ArrayList<>(frameCount);
        for (int i = 0; i < frameCount; i++) {
            byte expectedAddr = (byte) (moduleAddr + i); // 地址从模块地址开始递增
            byte[] frame = receiveFrameWithAddr(funcCode, expectedAddr);
            respFrames.add(frame);
        }
        return respFrames;
    }

    /**
     * 接收单帧响应并校验功能码和地址
     *
     * @param expectedFunc 期望功能码
     * @return 响应帧（10字节）
     * @throws IOException 接收失败或校验不通过时抛出
     */
    private byte[] receiveFrame(byte expectedFunc) throws IOException {
        return receiveFrameWithAddr(expectedFunc, (byte) moduleAddr);
    }

    /**
     * 接收单帧响应并校验功能码和指定地址
     *
     * @param expectedFunc 期望功能码
     * @param expectedAddr 期望地址
     * @return 响应帧（10字节）
     * @throws IOException 接收失败或校验不通过时抛出
     */
    private byte[] receiveFrameWithAddr(byte expectedFunc, byte expectedAddr) throws IOException {
        byte[] respFrame = new byte[FRAME_TOTAL_LENGTH];
        int totalRead = 0;

        // 读取完整10字节
        while (totalRead < FRAME_TOTAL_LENGTH) {
            int readLen = inputStream.read(respFrame, totalRead, FRAME_TOTAL_LENGTH - totalRead);
            if (readLen == -1) {
                throw new IOException("连接关闭，未收到完整响应（已读" + totalRead + "字节）");
            }
            totalRead += readLen;
        }

        // 校验功能码和地址
        if (respFrame[0] != expectedFunc) {
            throw new IOException("功能码不匹配，发送:0x" + bytesToHex(new byte[]{expectedFunc}) +
                    ",接收:0x" + bytesToHex(new byte[]{respFrame[0]}));
        }
        if (respFrame[1] != expectedAddr) {
            throw new IOException("地址不匹配，预期:0x" + bytesToHex(new byte[]{expectedAddr}) +
                    ",接收:0x" + bytesToHex(new byte[]{respFrame[1]}));
        }

        log.debug("接收响应 - 功能码:0x{}, 地址:0x{}, 数据域:{}",
                bytesToHex(new byte[]{respFrame[0]}),
                bytesToHex(new byte[]{respFrame[1]}),
                bytesToHex(getDataFromFrame(respFrame)));
        return respFrame;
    }

    /**
     * 从帧中提取数据域（第3-10字节）
     *
     * @param frame 完整帧（10字节）
     * @return 数据域（8字节）
     */
    private byte[] getDataFromFrame(byte[] frame) {
        byte[] data = new byte[DATA_LENGTH];
        System.arraycopy(frame, 2, data, 0, DATA_LENGTH);
        return data;
    }


    /**
     * 写入开关量输出状态
     *
     * @param channelStates 键：通道号（1-48），值：true=闭合，false=断开
     * @throws IOException            通信失败时抛出
     * @throws IllegalArgumentException 通道号超出范围时抛出
     */
    public void writeDigitalOutput(Map<Integer, Boolean> channelStates) throws IOException {
//        log.info("写入开关量 - 通道状态: {}", channelStates);
        byte[] data = new byte[DATA_LENGTH];
        for (Map.Entry<Integer, Boolean> entry : channelStates.entrySet()) {
            int channel = entry.getKey();
            boolean isOn = entry.getValue();
            if (channel < 1 || channel > 48) {
                throw new IllegalArgumentException("开关量通道号必须为1-48（当前：" + channel + "）");
            }
            int byteIdx = (channel - 1) / 8; // 每字节对应8个通道
            int bitIdx = (channel - 1) % 8;
            data[byteIdx] = isOn ?
                    (byte) (data[byteIdx] | (1 << bitIdx)) :
                    (byte) (data[byteIdx] & ~(1 << bitIdx));
        }
        sendFrame(FUNC_WRITE_DIGITAL, data);
//        log.info("开关量写入完成");
    }

    /**
     * 读取开关量继电器状态
     *
     * @return 键：通道号（1-48），值：true=闭合，false=断开
     * @throws IOException 通信失败时抛出
     */
    public Map<Integer, Boolean> readDigitalOutput() throws IOException {
//        log.info("读取开关量状态");
        byte[] data = new byte[DATA_LENGTH];
        byte[] respFrame = sendFrame(FUNC_READ_DIGITAL, data);
        byte[] respData = getDataFromFrame(respFrame);

        Map<Integer, Boolean> states = new HashMap<>();
        for (int byteIdx = 0; byteIdx < 6; byteIdx++) { // 6字节对应48通道
            byte b = respData[byteIdx];
            for (int bitIdx = 0; bitIdx < 8; bitIdx++) {
                int channel = byteIdx * 8 + bitIdx + 1;
                if (channel > 48) break;
                states.put(channel, (b & (1 << bitIdx)) != 0);
            }
        }
//        log.info("开关量读取完成 - 状态数: {}", states.size());
        return states;
    }

    /**
     * 读取开关量输入口状态
     *
     * @return 键：通道号（1-48），值：true=闭合，false=断开
     * @throws IOException 通信失败时抛出
     */
    public Map<Integer, Boolean> readDigitalInput() throws IOException {
//        log.info("读取开关量状态");
        byte[] data = new byte[DATA_LENGTH];
        byte[] respFrame = sendFrame(FUNC_ANALOG_SAMPLING_READ, data);
        byte[] respData = getDataFromFrame(respFrame);

        Map<Integer, Boolean> states = new HashMap<>();
        for (int byteIdx = 0; byteIdx < 6; byteIdx++) { // 6字节对应48通道
            byte b = respData[byteIdx];
            for (int bitIdx = 0; bitIdx < 8; bitIdx++) {
                int channel = byteIdx * 8 + bitIdx + 1;
                if (channel > 48) break;
                states.put(channel, (b & (1 << bitIdx)) != 0);
            }
        }
//        log.info("开关量读取完成 - 状态数: {}", states.size());
        return states;
    }


    /**
     * 写入模拟量输出值（自动分组处理1-12通道）
     *
     * @param channelValues 键：通道号（1-12），值：输出值（mV或uA，0-65535）
     * @throws IOException            通信失败时抛出
     * @throws IllegalArgumentException 通道号或值超出范围时抛出
     */
    public void writeAnalog(Map<Integer, Integer> channelValues) throws IOException {
        if (channelValues.isEmpty()) {
            log.warn("模拟量写入：无通道数据");
            return;
        }
//        log.info("写入模拟量 - 通道数: {}", channelValues.size());

        // 校验参数
        for (int channel : channelValues.keySet()) {
            if (channel < 1 || channel > 12) {
                throw new IllegalArgumentException("模拟量输出通道号必须为1-12（当前：" + channel + "）");
            }
            int value = channelValues.get(channel);
            if (value < 0 || value > 0xFFFF) {
                throw new IllegalArgumentException("模拟量值必须为0-65535（通道" + channel + "：" + value + "）");
            }
        }

        // 按范围分组（1-4/5-8/9-12）
        Map<String, Map<Integer, Integer>> groupMap = groupChannels(channelValues);

        // 逐组发送
        for (Map.Entry<String, Map<Integer, Integer>> group : groupMap.entrySet()) {
            String range = group.getKey();
            Map<Integer, Integer> groupChannels = group.getValue();
            Byte funcCode = ANALOG_WRITE_FUNC_MAP.get(range);
            if (funcCode == null) {
                throw new IllegalStateException("未找到通道范围[" + range + "]的功能码");
            }

            // 构造数据域（每个通道2字节，大端）
            byte[] data = new byte[DATA_LENGTH];
            int start = Integer.parseInt(range.split("-")[0]);
            for (Map.Entry<Integer, Integer> entry : groupChannels.entrySet()) {
                int channel = entry.getKey();
                int value = entry.getValue();
                int indexInGroup = channel - start; // 组内索引（0-3）
                byte[] valueBytes = intTo2Bytes(value);
                data[indexInGroup * 2] = valueBytes[0];
                data[indexInGroup * 2 + 1] = valueBytes[1];
            }

            sendFrame(funcCode, data);
//            log.info("模拟量{}写入完成", range);
        }
    }

    /**
     * 读取模拟量输出值（自动分组处理1-12通道）
     *
     * @param channels 要读取的通道列表（1-12）
     * @return 键：通道号，值：测量值（mV或uA）
     * @throws IOException            通信失败时抛出
     * @throws IllegalArgumentException 通道号无效或为空时抛出
     */
    public Map<Integer, Integer> readAnalog(List<Integer> channels) throws IOException {
        if (channels.isEmpty()) {
            throw new IllegalArgumentException("请指定至少一个模拟量输出通道（1-12）");
        }
//        log.info("读取模拟量输出 - 通道: {}", channels);

        // 校验通道
        for (int channel : channels) {
            if (channel < 1 || channel > 12) {
                throw new IllegalArgumentException("模拟量输出通道号必须为1-12（当前：" + channel + "）");
            }
        }

        // 按范围分组
        Map<String, List<Integer>> groupMap = new HashMap<>();
        for (int channel : channels) {
            String range = getAnalogOutputRange(channel);
            groupMap.computeIfAbsent(range, k -> new ArrayList<>()).add(channel);
        }

        // 逐组读取并合并结果
        Map<Integer, Integer> result = new HashMap<>();
        for (Map.Entry<String, List<Integer>> group : groupMap.entrySet()) {
            String range = group.getKey();
            List<Integer> groupChannels = group.getValue();
            Byte funcCode = ANALOG_READ_FUNC_MAP.get(range);
            if (funcCode == null) {
                throw new IllegalStateException("未找到通道范围[" + range + "]的功能码");
            }

            // 发送读取请求
            byte[] data = new byte[DATA_LENGTH];
            byte[] respFrame = sendFrame(funcCode, data);
            byte[] respData = getDataFromFrame(respFrame);

            // 解析响应（每个通道2字节，大端）
            int start = Integer.parseInt(range.split("-")[0]);
            for (int channel : groupChannels) {
                int indexInGroup = channel - start;
                int value = bytesToInt(respData[indexInGroup * 2], respData[indexInGroup * 2 + 1]);
                result.put(channel, value);
            }
//            log.info("模拟量输出{}读取完成", range);
        }

        return result;
    }

    /**
     * 读取模拟量采样模块值（1-18通道，功能码0x03，多帧响应）
     *
     * @param channels 要读取的通道列表（1-18）
     * @return 键：通道号，值：采样值（mV或uA）
     * @throws IOException            通信失败时抛出
     * @throws IllegalArgumentException 通道号无效或为空时抛出
     */
    public Map<Integer, Integer> readAnalogSampling(List<Integer> channels) throws IOException {
        if (channels.isEmpty()) {
            throw new IllegalArgumentException("请指定至少一个模拟量采样通道（1-18）");
        }
//        log.info("读取模拟量采样 - 通道: {}", channels);

        // 1. 校验通道合法性
        for (int channel : channels) {
            if (channel < 1 || channel > 18) {
                throw new IllegalArgumentException("模拟量采样通道号必须为1-18（当前：" + channel + "）");
            }
        }

        // 2. 按通道范围分组（对应5个响应帧）
        Map<String, List<Integer>> groupMap = new HashMap<>();
        for (int channel : channels) {
            String range = getAnalogSamplingRange(channel);
            groupMap.computeIfAbsent(range, k -> new ArrayList<>()).add(channel);
        }

        // 3. 发送请求并接收5个响应帧（功能码0x03，数据域全0）
        byte[] data = new byte[DATA_LENGTH]; // 数据域全0，如示例：00 00 00 00 00 00 00 00
        List<byte[]> respFrames = sendFrameMultiResponse(FUNC_ANALOG_SAMPLING_READ, data, 5);

        // 4. 解析对应帧的数据
        Map<Integer, Integer> result = new HashMap<>();
        for (Map.Entry<String, List<Integer>> group : groupMap.entrySet()) {
            String range = group.getKey();
            List<Integer> groupChannels = group.getValue();
            Integer frameIndex = ANALOG_SAMPLING_FRAME_INDEX_MAP.get(range);
            if (frameIndex == null || frameIndex >= respFrames.size()) {
                throw new IllegalStateException("未找到通道范围[" + range + "]对应的响应帧");
            }

            // 获取该范围对应的响应帧数据域
            byte[] respData = getDataFromFrame(respFrames.get(frameIndex));
            int startChannel = Integer.parseInt(range.split("-")[0]);

            // 解析组内通道值（每个通道2字节，大端）
            for (int channel : groupChannels) {
                int indexInGroup = channel - startChannel; // 组内索引（0-3，17-18为0-1）
                // 校验索引合法性（避免越界）
                if (indexInGroup < 0 || indexInGroup * 2 + 1 >= respData.length) {
                    throw new IllegalArgumentException("通道" + channel + "在范围[" + range + "]中索引无效");
                }
                int value = bytesToInt(respData[indexInGroup * 2], respData[indexInGroup * 2 + 1]);
                result.put(channel, value);
            }
//            log.info("模拟量采样{}读取完成", range);
        }

        return result;
    }


    /**
     * 将模拟量输出通道按范围分组（1-4/5-8/9-12）
     */
    private Map<String, Map<Integer, Integer>> groupChannels(Map<Integer, Integer> channelValues) {
        Map<String, Map<Integer, Integer>> groupMap = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : channelValues.entrySet()) {
            int channel = entry.getKey();
            String range = getAnalogOutputRange(channel);
            groupMap.computeIfAbsent(range, k -> new HashMap<>()).put(channel, entry.getValue());
        }
        return groupMap;
    }

    /**
     * 获取模拟量输出通道所属范围（1-12通道）
     */
    private String getAnalogOutputRange(int channel) {
        if (channel >= 1 && channel <= 4) {
            return "1-4";
        } else if (channel >= 5 && channel <= 8) {
            return "5-8";
        } else if (channel >= 9 && channel <= 12) {
            return "9-12";
        } else {
            throw new IllegalArgumentException("无效模拟量输出通道：" + channel);
        }
    }

    /**
     * 获取模拟量采样通道所属范围（1-18通道）
     */
    private String getAnalogSamplingRange(int channel) {
        if (channel >= 1 && channel <= 4) {
            return "1-4";
        } else if (channel >= 5 && channel <= 8) {
            return "5-8";
        } else if (channel >= 9 && channel <= 12) {
            return "9-12";
        } else if (channel >= 13 && channel <= 16) {
            return "13-16";
        } else if (channel >= 17 && channel <= 18) {
            return "17-18";
        } else {
            throw new IllegalArgumentException("无效模拟量采样通道：" + channel);
        }
    }

    /**
     * int转2字节数组（大端）
     */
    private byte[] intTo2Bytes(int value) {
        return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
    }

    /**
     * 2字节数组（大端）转int
     */
    private int bytesToInt(byte b1, byte b2) {
        return ((b1 & 0xFF) << 8) | (b2 & 0xFF);
    }


    /**
     * 建立socket连接
     */
    private void connect() throws IOException {
        if (socket != null && !socket.isClosed()) {
            log.warn("已存在有效连接，无需重复连接");
            return;
        }
        try {
            socket = new Socket(ip, port);
            socket.setSoTimeout(SOCKET_TIMEOUT);
            inputStream = socket.getInputStream();
            outputStream = socket.getOutputStream();
        } catch (SocketTimeoutException e) {
            log.error("连接超时 - IP: {}, 端口: {}", ip, port, e);
        } catch (IOException e) {
            log.error("连接失败 - IP: {}, 端口: {}", ip, port, e);
        }
    }

    /**
     * 校验模块地址合法性
     */
    private int validateModuleAddr(int addr) {
        if (addr < 1 || addr > 255) {
            throw new IllegalArgumentException("模块地址必须为1-255（当前：" + addr + "）");
        }
        return addr;
    }

    /**
     * 字节数组转十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) return "[]";
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02X", bytes[i]));
            if (i < bytes.length - 1) sb.append(", ");
        }
        return sb.append("]").toString();
    }

    /**
     * 关闭连接资源
     */
    @Override
    public void close() {
        try {
            //        log.info("关闭连接");
            if (inputStream != null) inputStream.close();
            if (outputStream != null) outputStream.close();
            if (socket != null && !socket.isClosed()) socket.close();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }

    }


    // 测试方法
    public static void main(String[] args) {
        String ip = "192.168.0.7";
        int port = 20108;

        // 模块地址1，响应帧地址为1-5
        // 测试 模拟量采样 模块读取（1-18通道）
        try (CanIoTool tool = new CanIoTool(ip, port, 1)) {
            List<Integer> samplingChannels = Arrays.asList(1, 2, 3, 9, 10, 11);
            Map<Integer, Integer> samplingResult = tool.readAnalogSampling(samplingChannels);
            System.out.println("模拟量采样读取结果: " + samplingResult);
        } catch (IOException e) {
            log.error("模拟量采样异常", e);
        }

        // 测试 开关量输出
        try (CanIoTool tool = new CanIoTool(ip, port, 6)) {
            Map<Integer, Boolean> digitalStates = new HashMap<>();
            digitalStates.put(3, true);
            digitalStates.put(5, true);
            digitalStates.put(8, true);
            digitalStates.put(10, true);
            digitalStates.put(13, true);
            tool.writeDigitalOutput(digitalStates);
            Map<Integer, Boolean> readDigital = tool.readDigitalOutput();
            System.out.println("开关量输出状态: " + readDigital);
        } catch (IOException e) {
            log.error("开关量输出异常", e);
        }

        // 测试 开关量采样
        try (CanIoTool tool = new CanIoTool(ip, port, 7)) {
            Map<Integer, Boolean> readDigital = tool.readDigitalInput();
            System.out.println("开关量采样状态: " + readDigital);
        } catch (IOException e) {
            log.error("开关量采样异常", e);
        }

        // 测试 模拟量 输出
//        try (CanIoTool tool = new CanIoTool(ip, port, 2)) {
//            Map<Integer, Integer> analogValues = new HashMap<>();
//            analogValues.put(1, 10000);  // 10V
//            analogValues.put(3, 5000);   // 5V
//            analogValues.put(6, 10000);  // 10mA
//            analogValues.put(10, 8000);  // 8mA
//            tool.writeAnalog(analogValues);
//
//            List<Integer> readChannels = Arrays.asList(1, 3, 6, 10);
//            Map<Integer, Integer> readAnalog = tool.readAnalog(readChannels);
//            System.out.println("模拟量读取结果: " + readAnalog);
//        } catch (IOException e) {
//            log.error("模拟量操作异常", e);
//        }

    }
}